Манипуляции с системным меню.
пример: sysmenu.zip
Системное меню - это всплывающее меню, назначаемое окну приложения системой. Его можно увидеть, если кликнуть на иконке в заголовке окна. Это меню назначается и управляется исключительно Windows, но Вы можете производить с ним нужные манипуляции.
Рассмотрим пример:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
SMenu: HMenu;
AddingItem: Boolean;
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
procedure EnableButton(Enable: Boolean);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
const
Id_my = $00a0;
procedure TForm1.FormCreate(Sender: TObject);
begin
SMenu := GetSystemMenu(HAndle,false);
end;
procedure TForm1.WMSysCommand(var Msg: TWMSysCommand);
begin
if Msg.CmdType = Id_My then
ShowMessage('Вы выбрали нестандартный пункт системного меню.');
inherited;
end;
procedure TForm1.Button1Click(Sender: TObject);
var mi: TMenuItemInfo;
begin
mi.cbSize := 44;
{Важно! Если присвоить Sizeof(mi) не будет работать}
mi.fMask := MIIM_DATA or MIIM_ID or MIIM_STATE or MIIM_TYPE;
mi.fType := MFT_STRING;
mi.fState := MFS_ENABLED;
mi.wID := Id_my;
mi.hSubMenu := 0;
mi.hbmpChecked := 0;
mi.hbmpUnchecked := 0;
mi.dwTypeData := PChar('Cвой пунк&т');
AddingItem := InsertMenuItem(SMenu,1,True,Mi);
EnableButton(AddingItem);
end;
procedure TForm1.EnableButton(Enable: Boolean);
begin
Button1.Enabled := not Enable;
Button2.Enabled := Enable;
Button3.Enabled := Enable;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
EnableMenuItem(SMenu,Id_My,MF_BYCOMMAND or MF_Grayed);
Button2.Enabled := False;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
DeleteMenu(SMenu,id_My, MF_BYCOMMAND);
AddingItem := False;
EnableButton(AddingItem);
end;
end. Для начала нужно получить идентификатор системного меню назначенного окну. В API есть специальная функция - GetSystemMenu. В обработчике OnCreate формы получаем идентификатор и сохраняем его для последующего использования.
procedure TForm1.FormCreate(Sender: TObject);
begin
SMenu := GetSystemMenu(Handle,false);
end;
На форме имеется три кнопки позволяющие производить манипуляции с системным меню. Первая кнопка, Button1, позволяет добавить пункт в системное меню, он будет называться "свой пункт".
procedure TForm1.Button1Click(Sender: TObject);
var mi: TMenuItemInfo;
begin
mi.cbSize := 44;
{Важно! Если присвоить Sizeof(mi) не будет работать}
mi.fMask := MIIM_DATA or MIIM_ID or MIIM_STATE or MIIM_TYPE;
mi.fType := MFT_STRING;
mi.fState := MFS_ENABLED;
mi.wID := Id_my;
mi.hSubMenu := 0;
mi.hbmpChecked := 0;
mi.hbmpUnchecked := 0;
mi.dwTypeData := PChar('Cвой пунк&т');
AddingItem := InsertMenuItem(SMenu,1,True,Mi);
EnableButton(AddingItem);
end;
Для добавления нового пункта используется функция InsertMenuItem. Перед добавлением пункта в меню необходимо заполнить структуру TMenuItemInfo. Эта структура содержит информацию о новом пункте меню. При заполнении структуры есть одна особенность, в поле cbSize, указывающий размер структуры в байтах, необходимо указать число 44. Если указать размер структуры, используя функцию Sizeof(), вызов InsertMenuItem закончится неудачно. Это происходит из-за различия описаний структуры в VCL и С++. Более подробную информацию можно получить в справке по API.
При выборе пункта системного меню, windows посылает приложению сообщение WM_SYSCOMMAND. Чтобы пункт меню реагировал на выбор необходимо обработать это сообщение.
procedure TForm1.WMSysCommand(var Msg: TWMSysCommand);
begin
if Msg.CmdType = Id_My then
ShowMessage('Вы выбрали нестандартный пункт системного меню.');
inherited;
end;
Здесь проверяется, выбран ли "свой пункт". Если да, Msg.CmdType = Id_My, выводится сообщение. Если нет, вызывается обработчик предка. Константа Id_My однозначно определяющая "свой пункт" должна быть ниже значения $0F000.
Вторая кнопка, Button2, делает "свой пункт" недоступным для использования.
procedure TForm1.Button2Click(Sender: TObject);
begin
EnableMenuItem(SMenu,Id_My,MF_BYCOMMAND or MF_Grayed);
Button2.Enabled := False;
end;
Для этого используется функция EnableMenuItem с соответствующими параметрами. Если Вы хотите произвести обратное действие, сделать пункт доступным пункт меню, необходимо вместо параметра MF_Grayed указать MF_ENABLED.
Третья кнопка, Button3, удаляет указанный пункт из меню.
procedure TForm1.Button3Click(Sender: TObject);
begin
DeleteMenu(SMenu,id_My, MF_BYCOMMAND);
AddingItem := False;
EnableButton(AddingItem);
end;
Для этого используется функция DeleteMenu.
Эти же манипуляции можно производить и со стандартными пунктами системного меню. Полный список стандартных команд системного меню можно посмотреть в справке по API, в статье WM_SYSCOMMAND.
Исходный текст примера: sysmenu.zip
|